home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / getty.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  17KB  |  756 lines

  1. /* getty - get tty speed            Author: Fred van Kempen */
  2.  
  3. /*
  4.  * GETTY  -     Initialize and serve a login-terminal for INIT.
  5.  *        Also, select the correct speed. The STTY() code
  6.  *        was taken from stty(1).c; which was written by
  7.  *        Andrew S. Tanenbaum.
  8.  *        If this program is called as 'uugetty', then it
  9.  *        also performs some tasks that are needed before
  10.  *        UUCP can use the line.
  11.  *
  12.  * Usage:    getty [-c filename] [-h] [-k] [-t] line [speed]
  13.  *
  14.  * Version:    3.4    02/17/90
  15.  *
  16.  * Author:    F. van Kempen, MicroWalt Corporation
  17.  */
  18.  
  19. #include <sys/types.h>
  20. #include <sgtty.h>
  21. #include <unistd.h>
  22. #include <utmp.h>
  23. #include <ctype.h>
  24. #include <signal.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <fcntl.h>
  28. #include <pwd.h>
  29.  
  30. #ifdef NULL    /* ugly, I know... */
  31. #    undef NULL
  32. #endif    /* NULL */
  33. #define NULL 0
  34.  
  35. #ifdef SIG_IGN    /* even more ugly... */
  36. #    undef SIG_IGN
  37. #    define SIG_IGN 1
  38. #endif    /* SIG_IGN */
  39.  
  40. #ifndef BITS8    /* new-style UNIX or MINIX */
  41. #    define BITS5 CS5
  42. #    define BITS6 CS6
  43. #    define BITS7 CS7
  44. #    define BITS8 CS8
  45. #endif    /* BITS8 */
  46.  
  47. #define GDEFS       "/etc/gettydefs"    /* pathname of getty definitions */
  48. #define ISSUE           "/etc/issue"    /* System-name textfile */
  49. #define LOGIN1           "/bin/login"
  50. #define LOGIN2           "/usr/bin/login"
  51. #define COMMENT              '#'    /* this char starts a comment-line */
  52. #define SEPA                 '#'    /* this char separates the fields */
  53. #define EOT                  '\004'
  54. #define EOF           (char) 0
  55. #define STARTC             021    /* CTRL-Q */
  56. #define STOPC             023    /* CTRL-S */
  57. #define QUITC             034    /* CTRL-\ */
  58. #define EOFC             004    /* CTRL-D */
  59. #define DELC               0177    /* DEL */
  60. #define ST_IDLE             44    /* the getty is idle */
  61. #define ST_RUNNING         55    /* getty is now RUNNING */
  62. #define ST_SUSPEND         66    /* getty was SUSPENDed for dialout */
  63.  
  64.  
  65. typedef struct {
  66.   char *label;            /* label of this entry */
  67.   char *flags1;            /* initial flags */
  68.   char *flags2;            /* final flags */
  69.   char *prompt;            /* login-prompt */
  70.   char *next;            /* next label in chain */
  71. } ENTRY;
  72.  
  73. #define clr1 tty.sg_flags &= ~(BITS5 | BITS6 | BITS7 | BITS8)
  74. #define clr2 tty.sg_flags &= ~(EVENP | ODDP)
  75.  
  76.  
  77. static char *Version = "@(#) GETTY 3.4 (02/17/90)";
  78.  
  79.  
  80. char *tty_name;            /* what is our TTY? */
  81. ENTRY gdefs[16];        /* we have space for 16 definitions */
  82. ENTRY *defs;            /* our GETTY definition */
  83. int uugetty = 0;        /* were we called as 'uugetty' ??? */
  84. int nohup = 0;            /* NO hangup on exit/close */
  85. int timeout = 0;        /* use TIMEOUT */
  86. int keyboard = 0;        /* are we using the Console? */
  87. int state = ST_IDLE;        /* the IDLE/SUSPEND/RUNNING state flag */
  88. struct sgttyb tty;        /* the current terminal state */
  89.  
  90.  
  91. void do_stty();            /* forward declaration */
  92.   
  93.  
  94. void sigcatch(sig)
  95. int sig;
  96. {
  97. /* Catch the signals that want to catch. */
  98.  
  99.   switch(sig) {
  100.     case SIGEMT:    /* SIGEMT means SUSPEND */
  101.         if (state == ST_IDLE) state = ST_SUSPEND;
  102.         break;
  103.     case SIGIOT:    /* SIGIOT means RESTART */
  104.         if (state == ST_SUSPEND) state = ST_RUNNING;
  105.         break;
  106.     case SIGBUS:    /* SIGBUS means IGNORE ALL */
  107.         signal(SIGEMT, SIG_IGN);
  108.         signal(SIGIOT, SIG_IGN);
  109.         state = ST_RUNNING;
  110.         break;
  111.   }
  112.   signal(sig, sigcatch);
  113. }
  114.  
  115.  
  116. char agetchar(fd)
  117. int fd;
  118. {
  119. /* Read a character, or EOF if zero chars read. */
  120.  
  121.   static char buf[1024];
  122.   static char *bufp = buf;
  123.   static int nleft = 0;
  124.  
  125.   if (nleft == 0) {
  126.     nleft = read(fd, buf, 1024);
  127.     bufp = buf;
  128.   }
  129.   return((--nleft >= 0) ? *bufp++ : EOF);
  130. }
  131.  
  132.  
  133. char *readline(fd)
  134. int fd;
  135. {
  136. /* Read one line from the defs-file. */
  137.  
  138.   char linbuff[512];
  139.   register int c, len;
  140.   register char *bp = linbuff;
  141.  
  142.   /* Read a line of text. */
  143.   len = 0;
  144.   while (1) {
  145.     c = agetchar(fd);
  146.     if (c == '\n' || c == EOF) break;
  147.     *bp++ = c;
  148.     len++;
  149.   }
  150.   *bp = '\0';
  151.  
  152.   /* Now allocate a buffer for it. */
  153.   bp = (char *)malloc(len + 1);
  154.   if (bp == (char *) NULL) return((char *) NULL);
  155.  
  156.   /* Copy this line to its buffer. */
  157.   strcpy(bp, linbuff);
  158.  
  159.   return((c == EOF) ? (char *) NULL : bp);
  160. }
  161.  
  162.  
  163. void decode(text, ep)
  164. char *text;
  165. ENTRY *ep;
  166. {
  167. /* Decode an input line. */
  168.  
  169.   register char *sp;
  170.  
  171.   sp = text;
  172.   while (*sp == ' ' || *sp == '\t') sp++;
  173.   ep->label = sp;            /* first, decode LABEL field */
  174.   while (*sp != '\0' && *sp != SEPA) sp++;
  175.   *sp++ = '\0';
  176.   while (*sp == ' ' || *sp == '\t') sp++;
  177.   ep->flags1 = sp;        /* next, INITIAL flags field */
  178.   while (*sp != '\0' && *sp != SEPA) sp++;
  179.   *sp++ = '\0';
  180.   while (*sp == ' ' || *sp == '\t') sp++;
  181.   ep->flags2 = sp;        /* then, FINAL flags field */
  182.   while (*sp != '\0' && *sp != SEPA) sp++;
  183.   *sp++ = '\0';
  184.   while (*sp == ' ' || *sp == '\t') sp++;
  185.   ep->prompt = sp;        /* and the LOGIN_PROMPT field */
  186.   while (*sp != '\0' && *sp != SEPA) sp++;
  187.   *sp++ = '\0';
  188.   while (*sp == ' ' || *sp == '\t') sp++;
  189.   ep->next = sp;        /* finally, decode the NEXT field */
  190.   while (*sp != '\0' && *sp != SEPA) sp++;
  191.   *sp++ = '\0';
  192. }
  193.  
  194.  
  195. int readdefs(name, label)
  196. char *name;
  197. char *label;
  198. {
  199. /* Read the defs-file. */
  200.  
  201.   int defsfd;            /* definition file */
  202.   int defidx;            /* definition index */
  203.   register char *bp;
  204.  
  205.   if ((defsfd = open(name, O_RDONLY)) < 0) return(defsfd);
  206.   defidx = 0;
  207.   defs = &gdefs[defidx];    /* set DEFAULT definition */
  208.   while (1) {
  209.     bp = readline(defsfd);
  210.     if (bp == (char *) NULL) break;
  211.     switch (*bp) {
  212.         case '\0':        /* blank line */
  213.         continue;
  214.         case '#':        /* comment line */
  215.         continue;
  216.         default:        /* data! */
  217.         decode(bp, &gdefs[defidx]);
  218.         if (label != (char *) NULL) {
  219.             if (!strcmp(gdefs[defidx].label, label))
  220.                 defs = &gdefs[defidx];
  221.         }
  222.         defidx++;
  223.     }
  224.   }
  225.   close(defsfd);
  226.   return(0);
  227. }
  228.  
  229.  
  230. void select()
  231. {
  232. /* Select next speed from the chain. */
  233.  
  234.   register int idx;
  235.  
  236.   idx = 0;
  237.   while (idx < 16) {
  238.     if (!(strcmp(gdefs[idx].label, defs->next))) {
  239.         defs = &gdefs[idx];
  240.         do_stty(defs->flags1);
  241.         return;
  242.     }
  243.     idx++;
  244.   }
  245. }
  246.  
  247.  
  248. void showfile(name)
  249. char *name;
  250. {
  251. /* Read a textfile and show it on the desired terminal. */
  252.  
  253.   register int fd;
  254.   register int len;
  255.   char buff[1024];
  256.  
  257.   if ((fd = open(name, O_RDONLY)) < 0) return;
  258.   while (1) {
  259.     len = read(fd, buff, 80);
  260.     if (len > 0)
  261.         write(1, buff, len);
  262.     else
  263.         break;
  264.   }
  265.   close(fd);
  266. }
  267.  
  268.  
  269. /* Perform some UTMP and WTMP accounting.
  270.  * This information is needed for programs like
  271.  * who(1), last(1) and write(1)...
  272.  */
  273. void wtmp(line)
  274. char *line;            /* tty device name */
  275. {
  276.   struct utmp entry, oldent;
  277.   char *blank = "               ";
  278.   register char *sp;
  279.   int fd, recno;
  280.   extern long time();
  281.  
  282.   /* Strip off the /dev part of the TTY name. */
  283.   sp = strrchr(line, '/');
  284.   if (sp == NULL) sp = line;
  285.     else sp++;
  286.  
  287.   /* First, read the current UTMP entry.  We need some of its
  288.    * parameters! (like PID, ID etc...)
  289.    */
  290.   if ((fd = open(UTMP, O_RDONLY)) < 0) return;
  291.   recno = 0;
  292.   while (read(fd, (char *) &oldent, (unsigned) sizeof(struct utmp))
  293.                         == sizeof(struct utmp)) {
  294.     if (oldent.ut_pid == getpid()) break;
  295.     recno++;
  296.   }
  297.   close(fd);
  298.   recno *= sizeof(struct utmp);
  299.  
  300.   /* Clear out the new string fields. */
  301.   strncpy(entry.ut_name, blank, sizeof(entry.ut_name));
  302.   strncpy(entry.ut_id, blank, sizeof(entry.ut_id));
  303.   strncpy(entry.ut_line, blank, sizeof(entry.ut_line));
  304.  
  305.   /* Enter new string fields. */
  306.   strcpy(entry.ut_name, "");
  307.   strncpy(entry.ut_id, oldent.ut_id, sizeof(entry.ut_id));
  308.   strncpy(entry.ut_line, sp, sizeof(entry.ut_line));
  309.  
  310.   /* Copy old numeric fields. */
  311.   entry.ut_pid = oldent.ut_pid;
  312.  
  313.   /* Change new numeric fields. */
  314.   entry.ut_type = LOGIN_PROCESS;/* we are waiting for a LOGIN! */
  315.   time((time_t *) &(entry.ut_time));
  316.  
  317.   /* Write a WTMP record. */
  318.   if ((fd = open(WTMP, O_WRONLY)) > 0) {
  319.     if (lseek(fd, 0L, SEEK_END) >= 0L) {
  320.         write(fd, (char *) &entry, sizeof(struct utmp));
  321.     }
  322.     close(fd);
  323.   }
  324.  
  325.   /* Rewrite the UTMP entry. */
  326.   if ((fd = open(UTMP, O_WRONLY)) > 0) {
  327.     if (lseek(fd, (long) recno, SEEK_SET) >= 0L) {
  328.         write(fd, (char *) &entry, sizeof(struct utmp));
  329.     }
  330.     close(fd);
  331.   }
  332. }
  333.  
  334.  
  335. /* Read one character from stdin.
  336.  * If it looks bad (highest bit set, or error return)
  337.  * try next speed in the list.
  338.  */
  339. int areadch()
  340. {
  341.   int ch, st;
  342.   char ch1;
  343.  
  344.   while (1) {
  345.     st = read(0, &ch1, 1);    /* read character from TTY */
  346.     if (st < 0) return(-1);    /* SIGNAL received! */
  347.  
  348.     ch = ch1 & 0xFF;
  349.     if (keyboard == 1) return(ch);
  350.  
  351.     if ((ch == 0) || ((ch & 128) == 128)) {
  352.         select();
  353.         ioctl(0, TIOCGETP, &tty);
  354.